package com.silverhaze.web.wot;

import com.silverhaze.web.data.wot.WoTDayStatistics;
import com.silverhaze.web.data.wot.WoTDayTankStatistics;
import com.silverhaze.web.data.wot.WoTPlayer;
import com.silverhaze.web.data.wot.WoTTank;
import com.silverhaze.web.util.EntityManageUtil;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: Babanin
 * Date: 25.11.11
 * Time: 23:54
 */
public class WoTStatisticsParser {

    private static final Logger LOGGER = Logger.getLogger(WoTStatisticsParser.class.getName());

    public static final String LAST_UPDATE_PATTERN = "js-datetime-format\"\\sdata-timestamp=\"([0-9]+)";
    public static final String BASE_INFORMATION_PATTERN = "<td class=\"td-number-nowidth\">\\s*([0-9]+)\\s*";
    public static final String BASE_TANK_INFORMATION_PATTERN = "<td class=\"value\"><a class=\"b-gray-link\" href=\"/encyclopedia/tanks/.{1,30}\">(.{1,20})</a></td><td class=\"right value\">([0-9]+)</td><td class=\"right value\">([0-9]+)</td>";
    public static final String BASE_TANK_ICON_INFORMATION_PATTERN = "img class=\"png\" src=\"/static/(.{1,100}).png\"";

    public static WoTDayStatistics parse(ParserContext context, String webPage) {
        WoTDayStatistics dayStatistics = new WoTDayStatistics();

        webPage = prepareWebPage(webPage);
        parseLastUpdateTime(context, webPage);
        parseBaseInformation(context, webPage);
        parseBaseTankInformation(context, webPage);

        return dayStatistics;
    }

    private static String prepareWebPage(String webPage) {
        webPage = webPage.replaceAll("\\n", "");
        webPage = webPage.replaceAll("&nbsp;", "");
        webPage = webPage.replaceAll("  ", "");

        return webPage;
    }

    private static void parseLastUpdateTime(ParserContext context, String webPage) {
        Pattern pattern = Pattern.compile(LAST_UPDATE_PATTERN);
        Matcher matcher = pattern.matcher(webPage);

        if (matcher.find()) {
            Long lastUpdate = Long.valueOf(matcher.group(1));
            context.getPlayer().setLastUpdateTime(new Date(lastUpdate));
        } else {
            LOGGER.warn("Last update time not found on current page");
        }
    }

    private static void parseBaseInformation(ParserContext context, String webPage) {
        Pattern pattern = Pattern.compile(BASE_INFORMATION_PATTERN);
        Matcher matcher = pattern.matcher(webPage);

        WoTDayStatistics dayStatistics = new WoTDayStatistics();
        dayStatistics.setPlayer(context.player);
        
        if (matcher.find()) {
            dayStatistics.setBattles(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setWins(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setLooses(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setSurvive(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setKilled(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setDiscovered(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setAccuracy(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setDamagePoints(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setBaseAttackPoints(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setBaseDefencePoints(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setTotalExp(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setAverageExp(Integer.parseInt(matcher.group(1)));
        }

        if (matcher.find()) {
            dayStatistics.setMaxBattleExp(Integer.parseInt(matcher.group(1)));
        }

        context.setDayStatistics(EntityManageUtil.persist(dayStatistics));
    }

    private static void parseBaseTankInformation(ParserContext context, String webPage) {
        Pattern pattern = Pattern.compile(BASE_TANK_INFORMATION_PATTERN, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(webPage);

        List<String> tankImgs = new ArrayList<String>();
        pattern = Pattern.compile(BASE_TANK_ICON_INFORMATION_PATTERN, Pattern.MULTILINE);
        matcher = pattern.matcher(webPage);

        while (matcher.find()) {
            String tankIcon = "http://worldoftanks.ru/static/" + matcher.group(1) + ".png";
            tankImgs.add(tankIcon);
        }

        int imgIterator = 0;
        List<WoTDayTankStatistics> dayTankStatistics = new ArrayList<WoTDayTankStatistics>();
        while (matcher.find()) {
            int wins = Integer.parseInt(matcher.group(3));
            int battles = Integer.parseInt(matcher.group(2));
            String tankName = matcher.group(1);

            WoTTank currentTank = null;
            List<WoTTank> tanks = context.getTanks();
            for (WoTTank tank : tanks) {
                if (tank.getTankName().equals(tankName)) {
                    currentTank = tank;
                    currentTank.setTankImageUrl(tankImgs.get(imgIterator));

                    break;
                }
            }

            if (currentTank == null) {
                currentTank = new WoTTank();
                currentTank.setTankName(tankName);
                currentTank.setTankImageUrl(tankImgs.get(imgIterator));

                context.addNewTank(currentTank);
            }

            WoTDayTankStatistics dayTankStats = new WoTDayTankStatistics();
            dayTankStats.setBattles(battles);
            dayTankStats.setWin(wins);
            dayTankStats.setTank(currentTank);
            dayTankStats.setDayStatistics(context.getDayStatistics());

            dayTankStatistics.add(dayTankStats);
            imgIterator++;
        }

        for (WoTDayTankStatistics dayTankStats : dayTankStatistics) {
            EntityManageUtil.persist(dayTankStats);
        }
    }

    public static class ParserContext {
        private WoTPlayer player;
        private WoTDayStatistics dayStatistics;

        private List<WoTTank> tanks;

        public ParserContext(WoTPlayer player, WoTDayStatistics dayStatistics, List<WoTTank> tanks) {
            this.player = player;
            this.dayStatistics = dayStatistics;
            this.tanks = tanks;

            if (this.player == null) {
                LOGGER.error("Player can not be null");
            }

            if (this.dayStatistics == null) {
                this.dayStatistics = new WoTDayStatistics();
            }

            if (this.tanks == null) {
                this.tanks = new ArrayList<WoTTank>();
            }
        }

        public WoTPlayer getPlayer() {
            return player;
        }

        public WoTDayStatistics getDayStatistics() {
            return dayStatistics;
        }

        public void setDayStatistics(WoTDayStatistics dayStatistics) {
            this.dayStatistics = dayStatistics;
        }

        public List<WoTTank> getTanks() {
            return tanks;
        }

        public void addNewTank(WoTTank tank) {
            EntityManageUtil.persist(tank);
        }
    }
}
